home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 April: Mac OS SDK / Dev.CD Apr 99 SDK1.toast / Development Kits / Apple Color OneScanner SDK / Scan Image 1.0 / Source / displays.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-24  |  12.4 KB  |  504 lines  |  [TEXT/CWIE]

  1. /*************************************************************************************
  2. #
  3. #        displays.c
  4. #
  5. #        This segment handles the Display Manager notification and
  6. #        repositions application windows in response.
  7. #
  8. #        Author(s):     Michael Marinkovich
  9. #                    Apple Developer Technical Support
  10. #                    marink@apple.com
  11. #
  12. #        Modification History: 
  13. #
  14. #            4/3/96        MWM     Initial coding                     
  15. #
  16. #        Copyright © 1992-96 Apple Computer, Inc., All Rights Reserved
  17. #
  18. #
  19. #        You may incorporate this sample code into your applications without
  20. #        restriction, though the sample code has been provided "AS IS" and the
  21. #        responsibility for its operation is 100% yours.  However, what you are
  22. #        not permitted to do is to redistribute the source as "DSC Sample Code"
  23. #        after having made changes. If you're going to re-distribute the source,
  24. #        we require that you make it clear in the source that the code was
  25. #        descended from Apple Sample Code, but that you've made changes.
  26. #
  27. *************************************************************************************/
  28.  
  29. #include <Events.h>
  30. #include <ToolUtils.h>
  31. #include <Gestalt.h>
  32. #include <OSUtils.h>
  33.  
  34.  
  35. #include "App.h"
  36. #include "Proto.h"
  37.  
  38.  
  39. //----------------------------------------------------------------------
  40. //    Globals
  41. //----------------------------------------------------------------------
  42.  
  43. DMNotificationUPP        gDMNUPP;
  44. ProcessSerialNumber        gThePSN;
  45.  
  46.  
  47. //----------------------------------------------------------------------
  48. //
  49. //    InstallDMNotification - tell DM that we want to be notified by callback.
  50. //                      
  51. //                      
  52. //----------------------------------------------------------------------
  53.  
  54. OSErr InstallDMNotification(void)
  55. {
  56.     OSErr                    err;
  57.     
  58.     // use our process number so when we get called
  59.     // the A5 is ours
  60.     err = GetCurrentProcess(&gThePSN);
  61.     
  62.     if (err == noErr) 
  63.     {
  64.         gDMNUPP = NewDMNotificationProc(WorldChangedProc);
  65.         err = DMRegisterNotifyProc(gDMNUPP, &gThePSN);
  66.     }
  67.     
  68.     return err;
  69.     
  70. }    
  71.  
  72.  
  73. //----------------------------------------------------------------------
  74. //
  75. //    InstallAEDMNotification - tell DM that we want to be notified by AE.
  76. //                      
  77. //                      
  78. //----------------------------------------------------------------------
  79.  
  80. OSErr InstallAEDMNotification(void)
  81. {
  82.     OSErr        err;
  83.     
  84.     err = AEInstallEventHandler(kCoreEventClass, kAESystemConfigNotice,
  85.                                 NewAEEventHandlerProc(DoAEDisplayUpdate),
  86.                                 0L, false);
  87.  
  88.     return err;
  89.  
  90. }
  91.  
  92.  
  93. //----------------------------------------------------------------------
  94. //
  95. //    RemoveDMNotification - tell DM that we no longer want to be notified.
  96. //                      
  97. //                      
  98. //----------------------------------------------------------------------
  99.  
  100. OSErr RemoveDMNotification(void)
  101. {
  102.     OSErr                    err;
  103.     
  104.     err = DMRemoveNotifyProc(gDMNUPP, &gThePSN);
  105.     
  106.     return err;
  107.     
  108. }
  109.  
  110.  
  111. //----------------------------------------------------------------------
  112. //
  113. //    WorldChangedProc - Display Manager calls this proc when a depth or  
  114. //                       mode change is made. Your application should
  115. //                       handle window repositioning here. 
  116. //----------------------------------------------------------------------
  117.  
  118. pascal OSErr WorldChangedProc(AppleEvent *event)
  119. {
  120.     OSErr                    err;
  121.  
  122.     err = HandleNotification(event);
  123.     
  124.     return noErr;
  125.     
  126. }
  127.  
  128.  
  129. //----------------------------------------------------------------------
  130. //
  131. //    DoAEDisplayUpdate - Display Manager calls this proc when a depth or  
  132. //                        mode change is made. Your application should
  133. //                        handle window repositioning here. 
  134. //----------------------------------------------------------------------
  135.  
  136. pascal OSErr DoAEDisplayUpdate(AppleEvent event,AppleEvent reply,long refCon)
  137. {
  138.     OSErr                    err;
  139.  
  140.     err = HandleNotification(&event);
  141.  
  142.     return noErr;
  143.     
  144. }
  145.  
  146.  
  147. //----------------------------------------------------------------------
  148. //
  149. //    HandleNotification - handle the AppleEvent returned by either the 
  150. //                           callback or the AppleEvent procedure.
  151. //                      
  152. //----------------------------------------------------------------------
  153.  
  154. OSErr HandleNotification(AppleEvent *event)
  155. {
  156.     OSErr                    err;
  157.     GrafPtr                    oldPort;
  158.     AEDescList                displayList;
  159.     AEDescList                aDisplay;
  160.     AERecord                oldConfig,newConfig;
  161.     AEKeyword                tempWord;
  162.     DisplayIDType            displayID;
  163.     unsigned long            returnType;
  164.     long                    count;
  165.     Rect                    oldRect, newRect;
  166.     
  167.     GetPort(&oldPort);
  168.  
  169.     // Get a list of the displays from the Display Notice AppleEvent.
  170.     err = AEGetParamDesc(event,kAEDisplayNotice,typeWildCard,&displayList);
  171.     // How many items in the list
  172.     err = AECountItems(&displayList,&count);
  173.     
  174.     while (count > 0) // Loop through the list.
  175.     {
  176.         err = AEGetNthDesc(&displayList, count, typeWildCard, &tempWord, 
  177.                                     &aDisplay);
  178.         
  179.         // Get the Old Rect.            
  180.         err = AEGetNthDesc(&aDisplay, 1, typeWildCard, &tempWord, 
  181.                            &oldConfig);
  182.         err = AEGetKeyPtr(&oldConfig, keyDeviceRect, typeWildCard, 
  183.                           &returnType, &oldRect, 8, nil);
  184.         
  185.         // Get the DisplayID so we can get the GDevice later.                
  186.         err = AEGetKeyPtr(&oldConfig, keyDisplayID, typeWildCard, 
  187.                           &returnType, &displayID, 8, nil);
  188.  
  189.         // Get the New Rect.                
  190.         err = AEGetNthDesc(&aDisplay, 2, typeWildCard, &tempWord, 
  191.                            &newConfig);
  192.         err = AEGetKeyPtr(&newConfig, keyDeviceRect, typeWildCard, 
  193.                           &returnType, &newRect, 8, nil);
  194.         
  195.         // If the New and Old rects are not the same then we can assume
  196.         // the GDevice has changed and we need to rearrange the windows.
  197.         if (err == noErr && !EqualRect(&newRect, &oldRect))
  198.             HandleDeviceChange(displayID, &newRect);
  199.  
  200.         count--;
  201.         err = AEDisposeDesc(&aDisplay);
  202.         err = AEDisposeDesc(&oldConfig);
  203.         err = AEDisposeDesc(&newConfig);
  204.  
  205.     }
  206.     
  207.     err = AEDisposeDesc(&displayList);
  208.     SetPort(oldPort);
  209.     
  210.     return err;
  211.     
  212. }
  213.  
  214.  
  215. //----------------------------------------------------------------------
  216. //
  217. //    HandleDeviceChange - called when the oldconfig is different from 
  218. //                         newconfig. Will check all windows on effected 
  219. //                           device and move if needed.
  220. //----------------------------------------------------------------------
  221.  
  222. OSErr HandleDeviceChange(DisplayIDType displayID, Rect *newRect)
  223. {
  224.     OSErr        err = noErr;
  225.     GDHandle    gd;
  226.     GDHandle    onGD;
  227.     WindowRef    window;
  228.     
  229.     // Get the GDevice from the DisplayID.
  230.     err = DMGetGDeviceByDisplayID((DisplayIDType) displayID, &gd, false);
  231.  
  232.     if (err == noErr && gd != nil) 
  233.     {
  234.         window = FrontWindow();
  235.         
  236.         while (window != nil) 
  237.         {
  238.             SetPort(window); 
  239.             // which device holds the greatest portion of the window
  240.             onGD = GetGreatestDevice(window);
  241.             
  242.             // If the window is not 50% or greater on
  243.             // the desired device then pass it up.
  244.             if (onGD == gd) 
  245.             { 
  246.                 if (OutOfBoundsRect(gd, window, *newRect)) 
  247.                 {
  248.                     MoveInbounds(window, gd, *newRect); 
  249.                     if (OutOfBoundsRect(gd, window, *newRect)) 
  250.                     {
  251.                         ResizeInbounds(window, gd, *newRect);
  252.                         
  253.                         // If it is one of our document windows then we need
  254.                         // to reset the std state and the scroll bars.
  255.                         if (GetIsAppWindow(window))
  256.                             AdjustScrollbars(window, true);
  257.                     }        
  258.                 }
  259.                 ResetStdState(window);
  260.  
  261.             }    
  262.             window = (WindowRef)(((WindowPeek)window)->nextWindow);
  263.         }
  264.     }
  265.     
  266.     return err;
  267.     
  268. }
  269.  
  270.     
  271. //----------------------------------------------------------------------
  272. //
  273. //    OutOfBoundsRect -  check to see if the window is out of the device
  274. //                       rect.
  275. //                      
  276. //----------------------------------------------------------------------
  277.  
  278. Boolean OutOfBoundsRect(GDHandle gd, WindowRef window, Rect screenRect)
  279. {
  280.     Boolean        out = false;
  281.     Rect        windRect;
  282.     short        mHeight = 0;
  283.     
  284.     GetWindowRect(window, &windRect);
  285.     
  286.     if (gd == GetMainDevice())
  287.         mHeight = GetMBarHeight();
  288.  
  289.     if ((windRect.right > screenRect.right) || (windRect.bottom > screenRect.bottom))
  290.         out = true;
  291.  
  292.     if ((windRect.left < screenRect.left) || (windRect.top < screenRect.top + mHeight))
  293.         out = true;
  294.     
  295.     return out;
  296.     
  297. }
  298.     
  299.     
  300. //----------------------------------------------------------------------
  301. //
  302. //    MoveInbounds -  Move window on to desired device
  303. //                        
  304. //                      
  305. //----------------------------------------------------------------------
  306.  
  307. void MoveInbounds(WindowRef window, GDHandle gd, Rect screenRect)
  308. {
  309.     Rect        bounds;
  310.     short        mHeight = 0;
  311.     short        hGlobal;
  312.     short        vGlobal;
  313.         
  314.     GetWindowRect(window, &bounds);
  315.  
  316.     if (gd == GetMainDevice())
  317.         mHeight = GetMBarHeight();
  318.         
  319.     hGlobal = bounds.left;
  320.     vGlobal = bounds.top + kTitleBarHeight;
  321.     
  322.     // we want to make the left-top a priority so adjust it first
  323.     // as to override the bottom, right movements. This is so we
  324.     // can resize the window later. 
  325.     
  326.     if (((bounds.right - bounds.left) > (screenRect.right - screenRect.left)) ||
  327.         ((bounds.bottom - bounds.top) > 
  328.         ((screenRect.bottom - screenRect.top) - mHeight))) 
  329.     {
  330.         
  331.         // adjust left
  332.         if (bounds.left < screenRect.left)
  333.             hGlobal = screenRect.left + kFudgeFactor;
  334.         
  335.         // adjust top
  336.         if (bounds.top < screenRect.top + mHeight)
  337.             vGlobal = screenRect.top + kTitleBarHeight + mHeight + kFudgeFactor;
  338.  
  339.     }    
  340.     else 
  341.     {
  342.         // adjust left
  343.         if (bounds.left < screenRect.left)
  344.             hGlobal = screenRect.left + kFudgeFactor;
  345.         else 
  346.         {
  347.             // adjust right
  348.             if (bounds.right > screenRect.right)
  349.                 hGlobal = (screenRect.right - (bounds.right - bounds.left)) - kFudgeFactor;
  350.         }
  351.         
  352.         // adjust top
  353.         if (bounds.top < screenRect.top + mHeight)
  354.             vGlobal = screenRect.top + kTitleBarHeight + mHeight + kFudgeFactor;
  355.  
  356.         else 
  357.         {
  358.             // adjust bottom
  359.             if (bounds.bottom > screenRect.bottom)
  360.                 vGlobal = (screenRect.bottom -  kFudgeFactor -
  361.                           (bounds.bottom - bounds.top) + mHeight);
  362.         }        
  363.  
  364.     }
  365.     
  366.     MoveWindow(window, hGlobal, vGlobal,false);
  367.         
  368. }
  369.     
  370.  
  371. //----------------------------------------------------------------------
  372. //
  373. //    ResizeInbounds -  resize the window to fit in the graphics device
  374. //                        
  375. //                      
  376. //----------------------------------------------------------------------
  377.  
  378. void ResizeInbounds(WindowRef window, GDHandle gd, Rect screenRect)
  379. {
  380.     Rect        windRect;
  381.     short        h;
  382.     short        v;
  383.  
  384.     windRect = window->portRect;
  385.     // make the window bounds the size of the gdRect
  386.     // less the fudge factor.
  387.     h = windRect.right - windRect.left;
  388.     v = windRect.bottom - windRect.top;
  389.  
  390.     if (h > screenRect.right - screenRect.left)
  391.         h = ((screenRect.right - screenRect.left) - (kFudgeFactor * 2));
  392.     
  393.     if (v > screenRect.bottom - screenRect.top) 
  394.     {
  395.         v = ((screenRect.bottom - screenRect.top) - (kFudgeFactor * 2));
  396.         
  397.         // If we are on the main device then subtract the mBar
  398.         // height plus a fudge factor for a boundary. 
  399.         if (gd == GetMainDevice())
  400.             v -= (GetMBarHeight() + kTitleBarHeight);
  401.     }        
  402.  
  403.         
  404.     SizeWindow(window, h, v, true);
  405.  
  406. }
  407.     
  408.  
  409. //----------------------------------------------------------------------
  410. //
  411. //    GetGreatestDevice - find thw device that holds the greatest area 
  412. //                        of the window.
  413. //                      
  414. //----------------------------------------------------------------------
  415.  
  416. GDHandle GetGreatestDevice(WindowRef window)
  417. {
  418.     GDHandle    gd;
  419.     GDHandle    savedGD;
  420.     Rect        gdRect;
  421.     Rect        foundRect;
  422.     long        size;
  423.     long        greatest = nil;
  424.  
  425.     gd = DMGetFirstScreenDevice(dmOnlyActiveDisplays);
  426.     savedGD = gd;
  427.     
  428.     // Loop through the device list
  429.     while (gd != nil) 
  430.     {    
  431.         gdRect = (**gd).gdRect;
  432.         
  433.         GlobalToLocal(&topLeft(gdRect));
  434.         GlobalToLocal(&botRight(gdRect));
  435.         
  436.         if (SectRect(&window->portRect, &gdRect, &foundRect)) 
  437.         {
  438.             size = ((long)(foundRect.right - foundRect.left) * 
  439.                    (long)(foundRect.bottom - foundRect.top));
  440.             
  441.             if (size > greatest) 
  442.             {
  443.                 greatest = size;
  444.                 savedGD = gd;        // save the greatest device
  445.             }    
  446.         }
  447.         gd = DMGetNextScreenDevice(gd, dmOnlyActiveDisplays);
  448.     }
  449.     
  450.     return savedGD;
  451.     
  452. }
  453.  
  454.  
  455. //----------------------------------------------------------------------
  456. //
  457. //    GetWindowRect - return actual window rect in global coords
  458. //                    
  459. //                    
  460. //----------------------------------------------------------------------
  461.  
  462. void GetWindowRect(WindowRef window, Rect *windRect)
  463. {    
  464.     *windRect = window->portRect;
  465.     
  466.     // add the titlebar height for actual height
  467.     windRect->top -= kTitleBarHeight;
  468.     
  469.     LocalToGlobal(&TopLeft(*windRect));
  470.     LocalToGlobal(&BotRight(*windRect));
  471.  
  472.  
  473. }
  474.  
  475. //----------------------------------------------------------------------
  476. //
  477. //    ResetStdState - since we are now on a different size screen we need
  478. //                    to change the stdState window size so our zooming
  479. //                    will work properly.  
  480. //----------------------------------------------------------------------
  481.  
  482. void ResetStdState(WindowRef window)
  483. {
  484.     Rect        screenRect;
  485.     
  486.     screenRect = window->portRect;
  487.  
  488.     LocalToGlobal(&TopLeft(screenRect));
  489.     LocalToGlobal(&BotRight(screenRect));
  490.     
  491.     // with the new interfaces we could also use the
  492.     // SetWindowStandardState procedure. 
  493.     (**(WStateDataHandle)
  494.         ((WindowPeek)window)->dataHandle).stdState = screenRect;
  495.         
  496.  
  497. }
  498.     
  499.     
  500.  
  501.     
  502.     
  503.  
  504.